/* ----------------------------------------------------------------------------
* File: box_connection.h
*
* Desc: Declaration of CBoxConnection class
*
* Created: 22/02/2011, by Alexey Korshunov
* ---------------------------------------------------------------------------- */
#ifndef _BOX_CONNECTION_H_
#define _BOX_CONNECTION_H_

#include "file_logger.h"
#include "box_server.h"
#include "user_box.h"
#include "map_thread_safe.h"


class CBoxServer;
class CUserBox;


// Thread function for each connection to client
// param - pointer to a conn_environment structure
void* conn_thread_func(void *param);


/************************************************************************/
/*	Structure for initialization of connection object                   */
/************************************************************************/
typedef struct conn_init_info
{
	conn_init_info() : id(0), control_sock(-1), data_sock(-1)
	{
		memset(&remote_addr, 0, sizeof(remote_addr));
	}

	unsigned int id;				// identifier
	int control_sock;				// socket for control
	int data_sock;					// socket for data transfer
	struct sockaddr_in remote_addr;	// client remote address

}conn_init_info;

class CBoxConnection;


/************************************************************************/
/*	Structure to describe connection environment						*/
/************************************************************************/
typedef struct conn_environment
{
	conn_environment() : server(NULL), conn(NULL), box(NULL), logger(NULL), stop(true)
	{
		pthread_cond_init(&cv_start, NULL);
		pthread_mutex_init(&mutex_start, NULL);
		pthread_cond_init(&cv_stop, NULL);
		pthread_mutex_init(&mutex_stop, NULL);
	}

	~conn_environment()
	{
		pthread_cond_destroy(&cv_start);
		pthread_mutex_destroy(&mutex_start);
		pthread_cond_destroy(&cv_stop);
		pthread_mutex_destroy(&mutex_stop);
	}

	CBoxServer *server;
	CBoxConnection *conn;
	CUserBox *box;
	CFileLogger *logger;
	bool stop;

	int data_sock;
	int control_sock;
	struct sockaddr_in remoteaddr;

	pthread_cond_t cv_start;
	pthread_mutex_t mutex_start;
	pthread_cond_t cv_stop;
	pthread_mutex_t mutex_stop;

	void (*print)(const char*,...);
	void log_print(const char*,...)
	{

	}

}conn_environment;


/************************************************************************/
/*	CBoxConnection class to describe connection entity					*/
/************************************************************************/
class CBoxConnection
{
public:
	CBoxConnection(CBoxServer *parent);
	~CBoxConnection();


	// Init client
	int Init(const conn_init_info& info);
	// Start handling of connection
	int StartHandling();
	// Stop connection
	int StopHandling();


	// Authentification process
	int AuthProcess(char *username);
	// Get user info command
	int GetUserInfoCmd(const box_trans_header *header);
	// Get box info command
	int GetBoxInfoCmd(const box_trans_header *header);
	// Read file data command
	int ReadFileDataCmd(const box_trans_header *header);
	// New file data command
	int NewFileDataCmd(const box_trans_header *header);
	// Update file data command
	int UpdateFileDataCmd(const box_trans_header *header);
	// Delete file data command
	int DeleteFileDataCmd(const box_trans_header *header);


	// Get server object
	CBoxServer* GetServer() const { return m_env.server; }
	// Get id
	unsigned int GetId() const { return m_id; }
	// Get remote address
	const sockaddr_in* GetRemoteAddress() const { return &m_env.remoteaddr; }

private:	
	// Handling error
	int HandleCmdError(const char* error_msg);

	unsigned int m_id;
	conn_environment m_env;
	bool m_init;
	CFileLogger *m_logger;

	pthread_t m_thread;
};


/************************************************************************/
/*	CMapConnection class for thread-safe map of CBoxConnection objects	*/
/************************************************************************/
class CMapConnection : public CMapThreadSafe<CBoxConnection*>
{
public:
	CBoxConnection* FindConnectionById(unsigned int id)
	{
		typename MapInfo::iterator it;

		CMutexLocker lock(m_mutex_access);
		it = m_map.find(id);
		if (it != m_map.end())
			return it->second;
		else
			return NULL;
	}

	void Stop()
	{
		CMutexLocker lock(m_mutex_access);
		typename MapInfo::iterator it = m_map.begin();
		for (; it != m_map.end(); ++it)
			it->second->StopHandling();
	}
};


#endif // _BOX_CONNECTION_H_